/*********************************************************************************
Organization 					: 				Georgia Institute of Technology
  
Institute 						:				Cognitive Computing Group(CCL)
 
Authors							: 				Manish Mehta 
 												
Class							:				NoPeasantBOFix
 
Function						: 				A class for holding a composite 
												fix for situations when 
												No Peasant is available because 
												of a peasant getting killed and 
												correspondingly at the same time
												attacking units are idle
****************************************************************************/

package behavioradaptation.fixes;


import java.util.List;
import java.util.Vector;

import cbr.episodicCBR.EpisodicCBR;

import planninglanguage.goals.AbsoluteBuildUnitsGoal;
import planninglanguage.plans.AttackGroundBOPlan;
import planninglanguage.plans.BasicOperatorPlan;
import planninglanguage.plans.MultiPlan;
import planninglanguage.plans.Plan;
import planninglanguage.plans.SequentialPlan;
import planninglanguage.plans.SubGoalPlan;
import trace.Entry;
import trace.Trace;
import base.WargusUnit;
import behavioradaptation.analysisdata.AbstractedTrace;
import behavioradaptation.analysisdata.FPSuccessData;
import behavioradaptation.analysisdata.FixData;
import behavioradaptation.analysisdata.IdleData;
import behavioradaptation.analysisdata.KillData;
import behavioradaptation.analysisdata.PlanFailuresData;
import behavioradaptation.failurepattern.PeasKilledAvAttUnitsFP;
import behavioradaptation.reasoner.TraceHelpers;
public class NoPeasCompositeFix {

	public static void fix(List<PlanFailuresData> a_planFailuresList, AbstractedTrace a_abstractedtrace, FixData a_fxdata, EpisodicCBR a_cbr) throws Exception
	{	
		// Check whether Peasant Killed ---Available Attack units at the same time
		// pattern is active
		PeasKilledAvAttUnitsFP pkaau = new PeasKilledAvAttUnitsFP();	
		Vector <FPSuccessData> sdata = pkaau.detectPattern(a_abstractedtrace);
		Vector<WargusUnit> unitused = new Vector<WargusUnit> ();
		// For each of those situatons apply the fix of asking the attacking units 
		// to attack at that moment 
		for(int i = 0; i < sdata.size(); i++)
		{	
			FPSuccessData a_successdata = (FPSuccessData)sdata.get(0);
			basicfix(a_planFailuresList, a_abstractedtrace,
					a_fxdata, a_cbr, a_successdata, unitused);
		}	

	}
	/*
	 * Another fix (currently not being used) that can be used to fix the situation is to build a human tower
	 */
	public static void basicfix1(List<PlanFailuresData> a_planFailuresList, AbstractedTrace a_abstractedtrace, FixData a_fxdata, EpisodicCBR a_cbr, FPSuccessData sd, Vector<WargusUnit> unitused) throws Exception
	{
		KillData kd =  sd.getKillData();
		int traceindex = kd.getIndex();
		Vector<IdleData> idata = sd.getIdleData();	
		Trace a_trace = a_abstractedtrace.getTrace(); 
		Vector <AttackGroundBOPlan> agplist = new Vector <AttackGroundBOPlan> ();
		MultiPlan seqp = new SequentialPlan();
		AbsoluteBuildUnitsGoal bg = new AbsoluteBuildUnitsGoal("human-guard-tower", 2, 0);				
		SubGoalPlan sgp = new SubGoalPlan(bg, null, null, null);
		int modindex = 0;
		if((traceindex - 20)  >= 6)
			traceindex = traceindex - 20;
		Entry entry = (Entry) a_trace.get(traceindex);
		Plan pl = ((Entry)a_trace.get(traceindex)).getPlan();		
		while(!(pl instanceof BasicOperatorPlan))
		{
			traceindex--;
			if(traceindex > 0)
			{	
				pl = ((Entry)a_trace.get(traceindex)).getPlan();
				entry = ((Entry)a_trace.get(traceindex));
			}
			else 
				return;
		}	
		Plan p = pl.getParent();
		System.out.println("Parent is-------------------" + p);
		TraceHelpers.modifyCaseBase(pl, a_trace, sgp, entry, false, a_cbr);
	}
	/*
	 * Currently used fix it to ask these attacking units to attack 
	 */
	public static void basicfix(List<PlanFailuresData> a_planFailuresList, AbstractedTrace a_abstractedtrace, FixData a_fxdata, EpisodicCBR a_cbr, FPSuccessData sd, Vector<WargusUnit> unitused) throws Exception
	{
		KillData kd =  sd.getKillData();
		int traceindex = kd.getIndex();
		Vector<IdleData> idata = sd.getIdleData();	
		Trace a_trace = a_abstractedtrace.getTrace(); 
		Plan pl = ((Entry)a_trace.get(traceindex)).getPlan();
		Vector <AttackGroundBOPlan> agplist = new Vector <AttackGroundBOPlan> ();
		MultiPlan seqp = new SequentialPlan();
		for(int k = 0; k < idata.size(); k++)
		{
			IdleData idled = (IdleData)idata.get(k);
			int id = idled.getUnit().getUnitID();
			for(int l=0; l <unitused.size();l++)
			{
				WargusUnit u = (WargusUnit)unitused.get(l);
				int usedid = u.getUnitID();
				if(id == usedid)
					return;
					
			}	
			
			AttackGroundBOPlan agp = new AttackGroundBOPlan(id, 10, 10, null, null, null);
			agplist.add(agp);
			seqp.add(agp);
			unitused.add(idled.getUnit());			
		}	
		Entry entry = (Entry) a_trace.get(traceindex);
		while (!(entry.getPlan() instanceof BasicOperatorPlan))
		{
			if(traceindex > 0)
				entry = (Entry)a_trace.get(traceindex--);
			else return;
		}	
		pl = ((Entry)a_trace.get(traceindex)).getPlan();
		// Modify the Case base with the modified plan 
		TraceHelpers.modifyCaseBase(pl, a_trace, seqp , entry, false, a_cbr);
	}
}
